﻿//#if DEBUG
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
using Engine.Dtd.Schema;

namespace Engine.Sgml.Matching {
    internal static class MatchTestUtility {
        private static string ErrorMessage = "The match object has inconsistent bounds.";


        public static bool Verify(Match match) {
            SElement startElement = match.StartElement;
            SElement endElement = match.EndElement;
            int startIndex = match.StartIndex;
            int endIndex = match.EndIndex;

            if (startElement == null) {
                Debug.Assert(endElement == null, ErrorMessage);
                Debug.Assert(startIndex == 0, ErrorMessage);
                Debug.Assert(endIndex == 0, ErrorMessage);
                }
            else if (match.Captures.Count == 0 || !match.Captures.Any(c => c.Success)) {
                Debug.Assert(endElement != null, ErrorMessage);
                Debug.Assert(startIndex == startElement.OrderIndex + 1, ErrorMessage);
                Debug.Assert(endIndex == endElement.OrderIndex + 1, ErrorMessage);
                Debug.Assert(startIndex == endIndex, ErrorMessage);
                }
            else if (match.Type == AccordanceTypes.Inconsistent && !match.Captures.Any(c => c.Entity.IsInclusion)) {
                Debug.Assert(endElement != null, ErrorMessage);
                Debug.Assert(startIndex == endIndex, ErrorMessage);
                Debug.Assert(startElement == endElement, ErrorMessage);
                }
            else {
                Debug.Assert(endElement != null);
                Debug.Assert(startIndex == startElement.OrderIndex, ErrorMessage);
                Debug.Assert(endIndex == endElement.OrderIndex, ErrorMessage);
                Debug.Assert(startIndex <= endIndex, ErrorMessage);
                }
            if (match.Parent != null && match.HasMatches) {
                Debug.Assert(match.Parent.StartIndex <= match.StartIndex, ErrorMessage);
                Debug.Assert(match.Parent.EndIndex >= match.EndIndex, ErrorMessage);
                }
            if (match.Model.OrderType == DGroupOrderType.OnlyOne)
                VerifyMatchWithOnlyOneModel(match);
            Verify(match.Captures);
            return true;
            }

        private static void VerifyMatchWithOnlyOneModel(Match match) {
            var captures = from c in match.Captures
                           where c.Success && (!c.Entity.IsInclusion && !c.Entity.IsIllegalElement)
                           select c;
            if (captures.Count() > 1) {
                IModelGroupsNode model = captures.First().Entity.Model;
                if (captures.All(c => c.Entity.Model == model))
                    Debug.Assert(model.Occurrence == DElementOccurrence.OneOrMore || model.Occurrence == DElementOccurrence.ZeroOrMore || match.Model.Occurrence == DElementOccurrence.OneOrMore || match.Model.Occurrence == DElementOccurrence.ZeroOrMore, "The match object with only one model groups has too many capture objects.");
                else
                    Debug.Assert(match.Model.Occurrence == DElementOccurrence.OneOrMore || match.Model.Occurrence == DElementOccurrence.ZeroOrMore, "The match object with only one model groups has too many capture objects.");
                }
            }

        private static void Verify(CaptureCollection captures) {
            for (int i = 0, j = 1; j < captures.Count; i++, j++) {
                if (captures[i].Success) {
                    if (captures[j].Success)
                        Debug.Assert(captures[i].EndIndex < captures[j].StartIndex, ErrorMessage);
                    else {
                        while (++j < captures.Count) {
                            if (captures[j].Success) {
                                Debug.Assert(captures[i].EndIndex < captures[j].StartIndex, ErrorMessage);
                                i = j++;
                                break;
                                }
                            }
                        }
                    }
                }
            for (int i = 0; i < captures.Count; i++) {
                if (captures[i].Entity.IsModelMatch)
                    Verify(captures[i].Entity.Match);
                }
            }
        }
    }
//#endif